import {
  PerspectiveCamera,
  Raycaster,
  Scene,
  Vector2,
  WebGLRenderer,
} from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
import { TransformControls } from "three/examples/jsm/controls/TransformControls";
import mitt from "mitt";
export class Editor {
  /**
   * 场景
   */
  scene: Scene;
  /**
   * 相机
   */
  camera: PerspectiveCamera;
  /**
   * 渲染器
   */
  private renderer: WebGLRenderer;
  private transformControl: TransformControls;
  pointer = new Vector2();
  emitter = mitt();
  private tanFOV: number;
  private canvasHeight: number;
  constructor(canvas: HTMLCanvasElement) {
    this.scene = new Scene();
    this.camera = new PerspectiveCamera(
      70,
      canvas.clientWidth / canvas.clientHeight,
      1,
      10000
    );
    this.camera.position.set(0, 250, 1000);
    this.tanFOV = Math.tan(((Math.PI / 180) * this.camera.fov) / 2);
    this.canvasHeight = canvas.clientHeight;
    this.renderer = new WebGLRenderer({ canvas });
    const controls = new OrbitControls(this.camera, this.renderer.domElement);
    controls.addEventListener("change", this.render.bind(this));
    this.transformControl = new TransformControls(
      this.camera,
      this.renderer.domElement
    );
    this.transformControl.addEventListener("change", this.render.bind(this));
    this.transformControl.addEventListener("dragging-changed", (event) => {
      controls.enabled = !event.value;
    });

    this.scene.add(this.transformControl);

    this.transformControl.addEventListener("objectChange", () => {
      console.log("objectChange");
    });
    window.addEventListener("resize", this.render.bind(this));
    this.render();
  }
  private resizeRendererToDisplaySize(renderer: WebGLRenderer) {
    const canvas = renderer.domElement;
    const pixelRatio = window.devicePixelRatio;
    const width = (canvas.clientWidth * pixelRatio) | 0;
    const height = (canvas.clientHeight * pixelRatio) | 0;
    const needResize = canvas.width !== width || canvas.height !== height;
    if (needResize) {
      renderer.setSize(width, height, false);
    }
    return needResize;
  }
  render() {
    this.emitter.emit("render");
    if (this.resizeRendererToDisplaySize(this.renderer)) {
      const canvas = this.renderer.domElement;
      this.camera.aspect = canvas.clientWidth / canvas.clientHeight;
      this.camera.fov =
        (360 / Math.PI) *
        Math.atan(this.tanFOV * (canvas.clientHeight / this.canvasHeight));
      this.camera.updateProjectionMatrix();
    }
    this.renderer.render(this.scene, this.camera);
  }
}
